package example.hayukleung.recorder;

import android.app.Activity;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.widget.Button;
import android.util.Log;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaRecorder;
import android.media.MediaPlayer;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import example.hayukleung.voicerecoder.R;

/*
 * The application needs to have the permission to write to external storage
 * if the output file is written to the external storage, and also the
 * permission to record audio. These permissions must be set in the
 * application's AndroidManifest.xml file, with something like:
 *
 * <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 * <uses-permission android:name="android.permission.RECORD_AUDIO" />
 *
 */
public class ActivityRecorder extends Activity
{
	private static final String LOG_TAG = "ActivityRecorder";
	private static String mFileName = null;

	private Button mButtonRecord = null;
	private MediaRecorder mRecorder = null;

	private Button mButtonPlay = null;
	private MediaPlayer mPlayer = null;

	private ProgressBar mProgressBar;
	private TimeCount mTimeCount;
	private TextView mTextView;
	private int mProgressMax;

	private int mTimePrecision = 100; // ms
	
	private SimpleDateFormat sdf = new SimpleDateFormat("mm:ss", Locale.CHINA);
	
	private TextView mTextViewTest;
	
	private BoolListener mRecordListener = new BoolListener()
	{
		@Override
		public void onceON()
		{
			mButtonRecord.setText("Stop recording");
			mButtonPlay.setClickable(false);
		}

		@Override
		public void onceOFF()
		{
			mButtonRecord.setText("Start recording");
			mButtonPlay.setClickable(true);
		}

		@Override
		public boolean doON()
		{
			return startRecording();
		}

		@Override
		public boolean doOFF()
		{
			return stopRecording();
		}
	};

	private BoolListener mPlayListener = new BoolListener()
	{
		@Override
		public void onceON()
		{
			mButtonPlay.setText("Stop playing");
			mButtonRecord.setClickable(false);
		}

		@Override
		public void onceOFF()
		{
			mButtonPlay.setText("Start playing");
			mButtonRecord.setClickable(true);
		}

		@Override
		public boolean doON()
		{
			return startPlaying();
		}

		@Override
		public boolean doOFF()
		{
			return stopPlaying();
		}
	};

	private boolean startPlaying()
	{
		try
		{
			mPlayer = new MediaPlayer();
			mPlayer.setOnCompletionListener(new OnCompletionListener()
			{
				@Override
				public void onCompletion(MediaPlayer mp)
				{
					mTimeCount.cancel();
				}
			});
			mPlayer.setDataSource(mFileName);
			mPlayer.prepare();
			mProgressBar
			    .setMax(mProgressMax = (int) Math.ceil(mPlayer.getDuration() / mTimePrecision));
			mTimeCount = new TimeCount(mProgressMax * mTimePrecision, mTimePrecision);
			mPlayer.start();
			mTimeCount.start();
			return true;
		}
		catch (IOException e)
		{
			Log.e(LOG_TAG, "startPlaying() failed: " + e);
			return false;
		}
	}

	private boolean stopPlaying()
	{
		try
    {
			mPlayer.release();
			mPlayer = null;

			mTimeCount.cancel();
			mProgressBar.setProgress(0);
			
			return true;
    }
    catch (Exception e)
    {
    	Log.e(LOG_TAG, "stopPlaying() failed: " + e);
			return false;
    }
		
	}

	private boolean startRecording()
	{
		try
		{
			mRecorder = new MediaRecorder();
			mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
			mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
			mRecorder.setOutputFile(mFileName);
			mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
			mRecorder.setMaxDuration(60000); // 时长限定
			
			mTimeCount = new TimeCount((mProgressMax = 600) * mTimePrecision, mTimePrecision);
			mProgressBar.setMax(mProgressMax);
			mRecorder.prepare();
			mRecorder.start();
			mTimeCount.start();
			return true;
		}
		catch (IOException e)
		{
			Log.e(LOG_TAG, "startRecording() failed: " + e);
			return false;
		}
		catch (RuntimeException e)
		{
			Log.e(LOG_TAG, "startRecording() failed: " + e);
			return false;
		}

	}

	private boolean stopRecording()
	{
		try
    {
			if (null==mRecorder||null==mTimeCount||null==mProgressBar)
			{
				return false;
			}
			
			mRecorder.stop();
			mRecorder.release();
			mRecorder = null;

			mTimeCount.cancel();
			
			mProgressBar.setProgress(0);
			
			return true;
    }
    catch (NullPointerException e)
    {
    	Log.e(LOG_TAG, "stopRecording() failed: " + e);
    	return false;
    }
		catch (RuntimeException e)
		{
			Log.e(LOG_TAG, "stopRecording() failed: " + e);
    	return false;
		}
		
	}

	public ActivityRecorder()
	{
		mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
		mFileName += "/audiorecordtest.3gp";
	}

	@Override
	public void onCreate(Bundle bundle)
	{
		super.onCreate(bundle);
		setContentView(R.layout.activity_recorder);

		initWidget();
	}

	@Override
	public void onPause()
	{
		super.onPause();
		stopRecording();
		stopPlaying();
	}

	private void initWidget()
	{
		mButtonRecord = (Button) findViewById(R.id.btn$record);
		mButtonRecord.setText("Start recording");
		mButtonRecord.setOnClickListener(mRecordListener);

		mButtonPlay = (Button) findViewById(R.id.btn$play);
		mButtonPlay.setText("Start playing");
		mButtonPlay.setOnClickListener(mPlayListener);

		mProgressBar = (ProgressBar) findViewById(R.id.pb$timeProgress);
		mProgressBar.setMax(mProgressMax);
		mProgressBar.setProgress(0);
		
		mTextView = (TextView) findViewById(R.id.txt$timePass);
		mTextView.setText(sdf.format(new Date(0)));
		
		mTextViewTest = (TextView) findViewById(R.id.txt$test);
		mTextViewTest.setText("");
	}

	class TimeCount extends CountDownTimer
	{
		private long totalMS;
		
		public TimeCount(long millisInFuture, long countDownInterval)
		{// 参数依次为总时长,和计时的时间间隔
			super(millisInFuture, countDownInterval);
			totalMS = millisInFuture;
		}

		@Override
		public void onFinish()
		{// 计时完毕时触发
			mProgressBar.setProgress(mProgressMax);
			mTextView.setText(sdf.format(new Date(0)));
		}

		@Override
		public void onTick(long millisUntilFinished)
		{// 计时过程显示
			/*
			mProgressBar.setProgress(mProgressMax
			    - (int) Math.ceil(millisUntilFinished / 1000) + 1);
			*/
			mProgressBar.incrementProgressBy(1);
			mTextView.setText(sdf.format(new Date(totalMS - millisUntilFinished)));
		}

	}

}
